package oop.ex2.main;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * An Enum for the variable type and their regex
 * 
 * @author yoavgoldstein
 * 
 */
enum VariableType {
    // The enums for the variable types
    INT("\\s*[-]?\\d+\\s*"), 
    DOUBLE("\\s*[-]?\\d+\\.\\d+|[-]?\\d*\\s*"), 
    STRING("\\s*\".*\"\\s*"), 
    BOOLEAN("\\s*true|false|[-]?\\d+|[-]?\\d+\\.?\\d+\\s*"), 
    CHAR("\\s*\'.\'\\s*"), 
    VOID("");

    //contains the enum REGEX
    private String regex;

    /**
     * An enum constructor
     * @param regex
     */
    private VariableType(String regex) {
        this.regex = regex;
    }

    /**
     * returns the specified enum regex
     * @return the regex of the specified enum
     */
    public String getRegex() {
        return regex;
    }
    /**
     * check the enum regex against an expression
     * @param regex - the regex to check
     * @param expression - the expression to match
     * @param type - the enum typr
     * @return true of the expression matches the regex, throws exception otherwise
     * @throws compileException
     */
    public boolean checkRegex(String regex, String expression, String type) throws compileException {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(expression);
        if (matcher.matches()) {
            return true;
        }
        else {
            throw new compileException(expression + " cannot be resolved as a type " + type);
        }
    }
}

/**
 * This class holds all the pattern for matching
 * @author yoavgoldstein
 *
 */
public class Patterns {

    // variable finals
    public static final String IS_FINAL = "\\s*(final)?\\s*";
    public static final String VARIABLE_TYPE = ("\\s*(int|double|String|boolean|char\\s)\\s*");
    public static final String VARIABLE_NAME = ("\\s*([\\_]?[a-zA-Z]+[[a-zA-Z]|\\_]*\\d*)\\s*");
    public static final String EQUALS = ("\\s*=\\s*");
    public static final String VARIABLE_VALUE = ("\\s*(.*)\\s*;");

    // method/conditionals finals
    public static final String OPEN_BRACKET = "\\s*\\(\\s*";
    public static final String CLOSE_BRACKET = "\\s*\\)\\s*";
    public static final String METHOD_NAME = ("\\s*([a-zA-Z]+[[a-zA-Z]|\\_]*\\d*)\\s*");
    public static final String METHOD_CALL = METHOD_NAME + OPEN_BRACKET + "(.*)" + CLOSE_BRACKET + ";";
    public static final String RETURN_TYPE = ("\\s*(void|int|double|String|boolean|char\\s)+\\s*");
    public static final String RETURN = "\\s*(return\\s*)\\s*";
    public static final String CONDITION = "\\s*\\(\\w\\)\\s*";

    // declaration finals
    public static final String VARIABLE_DECLARATION = IS_FINAL + VARIABLE_TYPE + "\\s*(.*)\\s*" + EQUALS
            + "(.*);\\s*" ;
    public static final String VARIABLE_SHORT_DECLARATION = IS_FINAL + VARIABLE_TYPE + "\\s*(.*)\\s*" + ";";
    public static final String VARIABLE_ASSAINMENT = VARIABLE_NAME + EQUALS + "(.*);";
    public static final String METHOD_DECLARATION = RETURN_TYPE + METHOD_NAME + OPEN_BRACKET + "\\s*(.*)\\s*"
            + CLOSE_BRACKET + "\\{\\s*";
    public static final String IF_WHILE_PATTERN = "\\s*(if|while\\s*)+\\s*" + OPEN_BRACKET + "(.*)"
            + CLOSE_BRACKET + "\\{\\s*";
    public static final String RETURN_STATEMENT = RETURN + VARIABLE_VALUE;

    private String regex;

    public Patterns(String regex) {
        // check type validity
        this.regex = regex;
    }

    public String getRegex() {
        return regex;
    }

    public boolean matches(String regex, String expression) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(expression);
        return matcher.matches();
    }

}
